﻿using SurfaceAd.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using Windows.ApplicationModel;
using Windows.Foundation;
using Windows.Storage;

/**
 * 创建时间：2014/9/22 11:03:47
 * 作者：yong.blackcore
 * Email：itblackhole@outlook.com
 * QQ：50404503
 * 描述：读取Package.appxmanifest文件（生成后在bin下是AppxManifest.xml名称）
 */
namespace SurfaceAd.Assistant
{
    public static class AppxManifestHelper
    {
        static AppxManifestHelper()
        {
            ResourcesLanguages = new List<string>();
        }

        ///// <summary>
        ///// 读取App配置文件
        ///// </summary>
        ///// <returns></returns>
        //private async static Task<XDocument> GetAppManifest()
        //{
        //    try
        //    {
        //        StorageFile storageFile = await Package.Current.InstalledLocation.GetFileAsync(Constants.AppManifest);
        //        string manifestXml = await FileIO.ReadTextAsync(storageFile);
        //        XDocument doc = XDocument.Parse(manifestXml);
        //        return doc;
        //    }
        //    catch { return null; }
        //}

        //private static XDocument GetDocument()
        //{
        //    return GetAppManifest().Result;
        //}

        //private async static Task<XDocument> AwaitGetDocument()
        //{
        //    var result = await Task.Factory.StartNew(() => GetDocument());
        //    return result;
        //}

        /// <summary>
        /// 提供出来的方法
        /// </summary>
        /// <returns></returns>
        public static IAsyncOperation<Boolean> LoadAppxManifestAsyncOperation()
        {
            return LoadAppxManifest().AsAsyncOperation();
        }


        private static async Task<Boolean> LoadAppxManifest()
        {
            //XDocument xDocument = await AwaitGetDocument();
            //if (!(xDocument != null && xDocument.Root != null))
            //    return false;

            XDocument xDocument = null;
            try
            {
                StorageFile storageFile = await Package.Current.InstalledLocation.GetFileAsync(Constants.AppManifest);
                string manifestXml = await FileIO.ReadTextAsync(storageFile);
                xDocument = XDocument.Parse(manifestXml);
            }
            catch (Exception err)
            {
                LogHelper.LogError(err.ToString(), typeof(AppxManifestHelper), "LoadAppxManifest");
                return false;
            }
            if (!(xDocument != null && xDocument.Root != null))
                return false;
            //        
            #region **********节点读取**********
            foreach (XElement element in xDocument.Root.Elements())
            {
                if (element == null)
                    continue;
                string elementName = element.Name.LocalName;
                if (string.IsNullOrWhiteSpace(elementName))
                    continue;
                //
                //LogHelper.LogInfo("------------" + elementName);
                //
                switch (elementName)
                {
                    case "Identity":
                        #region Identity
                        //var currentElement = element.Elements();
                        //foreach (XElement xe in currentElement)
                        //{
                        //    if (xe != null)
                        //        LogHelper.LogInfo("++++++" + xe.Name.LocalName);
                        //    var attrs = xe.Attributes();
                        //    foreach (XAttribute attr in attrs)
                        //    {
                        //        LogHelper.LogInfo("======" + attr.Name.ToString());
                        //    }
                        //}
                        //
                        //var attrs = xe.Attributes();
                        //    foreach (XAttribute attr in attrs)
                        //    {
                        //        LogHelper.LogInfo("======" + attr.Name.ToString());
                        //    }
                        var attrsIdentity = element.Attributes();
                        if (attrsIdentity != null && attrsIdentity.Count() > 0)
                        {
                            IdentityName = (from p in attrsIdentity where p.Name.LocalName.Equals("Name") select p.Value).FirstOrDefault<string>();
                            IdentityPublisher = (from p in attrsIdentity where p.Name.LocalName.Equals("Publisher") select p.Value).FirstOrDefault<string>();
                            IdentityVersion = (from p in attrsIdentity where p.Name.LocalName.Equals("Version") select p.Value).FirstOrDefault<string>();
                            IdentityProcessorArchitecture = (from p in attrsIdentity where p.Name.LocalName.Equals("ProcessorArchitecture") select p.Value).FirstOrDefault<string>();
                        }
                        //OutPutAppIdentityInfo();
                        break;
                        #endregion Identity
                    case "PhoneIdentity":
                        var attrsPhoneIdentity = element.Attributes();
                        if (attrsPhoneIdentity != null && attrsPhoneIdentity.Count() > 0)
                        {
                            PhoneIdentityPhoneProductId = (from p in attrsPhoneIdentity where p.Name.LocalName.Equals("PhoneProductId") select p.Value).FirstOrDefault<string>();
                            //TODO WPWRTC:PublisherId
                            //PhoneIdentityPhonePublisherId = (from p in attrsPhoneIdentity where p.Name.LocalName.Equals("PhonePublisherId") select p.Value).FirstOrDefault<string>();
                            PhoneIdentityPhonePublisherId = Package.Current.Id.PublisherId;
                        }
                        //OutPutAppPhoneIdentityInfo();
                        break;
                    case "Properties":
                        var eleProperties = element.Elements();
                        if (eleProperties != null && eleProperties.Count() > 0)
                        {
                            PropertiesDisplayName = (from p in eleProperties where p.Name.LocalName.Equals("DisplayName") select p.Value).FirstOrDefault<string>();
                            PropertiesPublisherDisplayName = (from p in eleProperties where p.Name.LocalName.Equals("PublisherDisplayName") select p.Value).FirstOrDefault<string>();
                            PropertiesLogo = (from p in eleProperties where p.Name.LocalName.Equals("Logo") select p.Value).FirstOrDefault<string>();
                        }
                        //OutPutAppPropertiesInfo();
                        break;
                    case "Prerequisites":
                        var elePrerequisites = element.Elements();
                        if (elePrerequisites != null && elePrerequisites.Count() > 0)
                        {
                            PrerequisitesOSMinVersion = (from p in elePrerequisites where p.Name.LocalName.Equals("OSMinVersion") select p.Value).FirstOrDefault<string>();
                            PrerequisitesOSMaxVersionTested = (from p in elePrerequisites where p.Name.LocalName.Equals("OSMaxVersionTested") select p.Value).FirstOrDefault<string>();
                        }
                        //OutPutAppPrerequisitesInfo();
                        break;
                    case "Resources":
                        ResourcesLanguages = new List<string>();
                        var eleResources = element.Elements();
                        if (eleResources != null && eleResources.Count() > 0)
                        {
                            foreach (XElement xe in eleResources)
                            {
                                var attrsResources = xe.Attributes();
                                if (attrsResources != null && attrsResources.Count() > 0)
                                {
                                    foreach (XAttribute xa in attrsResources)
                                    {
                                        ResourcesLanguages.Add(xa.Value);
                                    }
                                }
                            }
                        }
                        //OutPutAppResourcesInfo();
                        break;
                    case "Applications":
                        var eleApplications = element.Elements();
                        if (eleApplications != null && eleApplications.Count() > 0)
                        {
                            foreach (XElement xe in eleApplications)
                            {
                                var attrsApplications = xe.Attributes();
                                if (attrsApplications != null && attrsApplications.Count() > 0)
                                {
                                    ApplicationsId = (from p in attrsApplications where p.Name.LocalName.Equals("Id") select p.Value).FirstOrDefault<string>();
                                    ApplicationsExecutable = (from p in attrsApplications where p.Name.LocalName.Equals("Executable") select p.Value).FirstOrDefault<string>();
                                    ApplicationsEntryPoint = (from p in attrsApplications where p.Name.LocalName.Equals("EntryPoint") select p.Value).FirstOrDefault<string>();
                                }
                            }
                            var eleSubApplications = eleApplications.Elements().Attributes();
                            ApplicationsDisplayName = (from p in eleSubApplications where p.Name.LocalName.Equals("DisplayName") select p.Value).FirstOrDefault<string>();
                            ApplicationsDescription = (from p in eleSubApplications where p.Name.LocalName.Equals("Description") select p.Value).FirstOrDefault<string>();
                        }
                        //OutPutAppApplicationsInfo();
                        break;
                    case "Capabilities":
                        var eleCapabilities = element.Elements();
                        if (eleCapabilities != null && eleCapabilities.Count() > 0)
                        {
                            IsInternetClientCapability = CheckCapability(eleCapabilities, "internetClient");
                            IsInternetClientServerCapability = CheckCapability(eleCapabilities, "internetClientServer");
                            IsPrivateNetworkClientServerCapability = CheckCapability(eleCapabilities, "privateNetworkClientServer");
                            IsEnterpriseAuthenticationCapability = CheckCapability(eleCapabilities, "enterpriseAuthentication");
                            //
                            IsLocationCapability = CheckCapability(eleCapabilities, "location");
                            IsProximityCapability = CheckCapability(eleCapabilities, "proximity");
                            //
                            IsRemovableStorageCapability = CheckCapability(eleCapabilities, "removableStorage");
                            IsSharedUserCertificatesCapability = CheckCapability(eleCapabilities, "sharedUserCertificates");
                            IsMicrophoneCapability = CheckCapability(eleCapabilities, "microphone");
                            IsWebcamCapability = CheckCapability(eleCapabilities, "webcam");
                            //
                            IsVideosLibraryCapability = CheckCapability(eleCapabilities, "videosLibrary");
                            IsPicturesLibraryCapability = CheckCapability(eleCapabilities, "picturesLibrary");
                            IsMusicLibraryCapability = CheckCapability(eleCapabilities, "musicLibrary");
                        }
                        //OutPutAppCapabilitiesInfo();
                        break;
                    case "Extensions":
                        break;
                    case "Metadata":
                        break;
                }
            }
            #endregion 节点读取

            OutputPackageInfo();

            return true;
        }


        #region ******************************Identity******************************
        public static string IdentityName { get; private set; }
        public static string IdentityPublisher { get; private set; }
        public static string IdentityVersion { get; private set; }
        public static string IdentityProcessorArchitecture { get; private set; }
        private static void OutPutAppIdentityInfo()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine("");
            output.Append("IdentityName:\t").AppendLine(IdentityName);
            output.Append("IdentityPublisher:\t").AppendLine(IdentityPublisher);
            output.Append("IdentityVersion:\t").AppendLine(IdentityVersion);
            output.Append("IdentityProcessorArchitecture:\t").AppendLine(IdentityProcessorArchitecture);

            LogHelper.LogInfo(output.ToString(), typeof(AppxManifestHelper), "OutPutAppIdentityInfo");
        }
        #endregion  ******************************Identity******************************

        #region ******************************PhoneIdentity******************************
        public static string PhoneIdentityPhoneProductId { get; private set; }
        /// <summary>
        /// Package.Current.Id.PublisherId
        /// </summary>
        public static string PhoneIdentityPhonePublisherId { get; private set; }
        private static void OutPutAppPhoneIdentityInfo()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine("");
            output.Append("PhoneIdentityPhoneProductId:\t").AppendLine(PhoneIdentityPhoneProductId);
            output.Append("PhoneIdentityPhonePublisherId:\t").AppendLine(PhoneIdentityPhonePublisherId);

            LogHelper.LogInfo(output.ToString(), typeof(AppxManifestHelper), "OutPutAppPhoneIdentityInfo");
        }
        #endregion  ******************************PhoneIdentity******************************

        #region ******************************Properties******************************
        public static string PropertiesDisplayName { get; private set; }
        public static string PropertiesPublisherDisplayName { get; private set; }
        public static string PropertiesLogo { get; private set; }
        private static void OutPutAppPropertiesInfo()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine("");
            output.Append("PropertiesDisplayName:\t").AppendLine(PropertiesDisplayName);
            output.Append("PropertiesPublisherDisplayName:\t").AppendLine(PropertiesPublisherDisplayName);
            output.Append("PropertiesLogo:\t").AppendLine(PropertiesLogo);

            LogHelper.LogInfo(output.ToString(), typeof(AppxManifestHelper), "OutPutAppPropertiesInfo");
        }
        #endregion  ******************************Properties******************************

        #region ******************************Prerequisites******************************
        public static string PrerequisitesOSMinVersion { get; private set; }
        public static string PrerequisitesOSMaxVersionTested { get; private set; }
        private static void OutPutAppPrerequisitesInfo()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine("");
            output.Append("PrerequisitesOSMinVersion:\t").AppendLine(PrerequisitesOSMinVersion);
            output.Append("PrerequisitesOSMaxVersionTested:\t").AppendLine(PrerequisitesOSMaxVersionTested);

            LogHelper.LogInfo(output.ToString(), typeof(AppxManifestHelper), "OutPutAppPrerequisitesInfo");
        }
        #endregion  ******************************Prerequisites******************************

        #region ******************************Resources******************************
        public static IList<string> ResourcesLanguages { get; private set; }
        private static void OutPutAppResourcesInfo()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine("");
            if (ResourcesLanguages != null && ResourcesLanguages.Count() > 0)
            {
                foreach (string ResourcesLanguage in ResourcesLanguages)
                    output.Append("ResourcesLanguage:\t").AppendLine(ResourcesLanguage);
            }

            LogHelper.LogInfo(output.ToString(), typeof(AppxManifestHelper), "OutPutAppResourcesInfo");
        }
        #endregion  ******************************Resources******************************

        #region ******************************Applications******************************
        public static string ApplicationsId { get; private set; }
        public static string ApplicationsExecutable { get; private set; }
        public static string ApplicationsEntryPoint { get; private set; }
        public static string ApplicationsDisplayName { get; private set; }
        public static string ApplicationsDescription { get; private set; }
        private static void OutPutAppApplicationsInfo()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine("");
            output.Append("ApplicationsId:\t").AppendLine(ApplicationsId);
            output.Append("ApplicationsExecutable:\t").AppendLine(ApplicationsExecutable);
            output.Append("ApplicationsEntryPoint:\t").AppendLine(ApplicationsEntryPoint);
            output.Append("ApplicationsDisplayName:\t").AppendLine(ApplicationsDisplayName);
            output.Append("ApplicationsDescription:\t").AppendLine(ApplicationsDescription);

            LogHelper.LogInfo(output.ToString(), typeof(AppxManifestHelper), "OutPutAppPrerequisitesInfo");
        }
        #endregion  ******************************Applications******************************

        #region ******************************应用权限信息******************************
        public static Boolean IsInternetClientCapability { get; private set; }
        public static Boolean IsPrivateNetworkClientServerCapability { get; private set; }
        public static Boolean IsInternetClientServerCapability { get; private set; }
        public static Boolean IsEnterpriseAuthenticationCapability { get; private set; }
        public static Boolean IsLocationCapability { get; private set; }
        /// <summary>
        /// 邻近
        /// </summary>
        public static Boolean IsProximityCapability { get; private set; }

        public static Boolean IsPicturesLibraryCapability { get; private set; }
        public static Boolean IsMusicLibraryCapability { get; private set; }
        public static Boolean IsVideosLibraryCapability { get; private set; }
        public static Boolean IsMicrophoneCapability { get; private set; }
        public static Boolean IsWebcamCapability { get; private set; }
        public static Boolean IsRemovableStorageCapability { get; private set; }
        public static Boolean IsSharedUserCertificatesCapability { get; private set; }


        private static Boolean CheckCapability(IEnumerable<XElement> capabilities, String capabilityName)
        {
            XElement xElement = capabilities.FirstOrDefault<XElement>((XElement n) => n.Attribute("Name").Value.Equals(capabilityName));
            return xElement != null;
        }

        /// <summary>
        /// 输入应用的权限信息
        /// </summary>
        /// <returns></returns>
        private static void OutPutAppCapabilitiesInfo()
        {
            StringBuilder output = new StringBuilder();
            output.AppendLine("");
            output.Append("IsInternetClientCapability:\t").AppendLine(IsInternetClientCapability.ToString());
            output.Append("IsInternetClientServerCapability:\t").AppendLine(IsInternetClientServerCapability.ToString());
            output.Append("IsPrivateNetworkClientServerCapability:\t").AppendLine(IsPrivateNetworkClientServerCapability.ToString());
            output.Append("IsEnterpriseAuthenticationCapability:\t").AppendLine(IsEnterpriseAuthenticationCapability.ToString());
            output.Append("IsLocationCapability:\t").AppendLine(IsLocationCapability.ToString());
            output.Append("IsProximityCapability:\t").AppendLine(IsProximityCapability.ToString());
            output.Append("IsRemovableStorageCapability:\t").AppendLine(IsRemovableStorageCapability.ToString());
            output.Append("IsSharedUserCertificatesCapability:\t").AppendLine(IsSharedUserCertificatesCapability.ToString());
            output.Append("IsMicrophoneCapability:\t").AppendLine(IsMicrophoneCapability.ToString());
            output.Append("IsWebcamCapability:\t").AppendLine(IsWebcamCapability.ToString());
            output.Append("IsVideosLibraryCapability:\t").AppendLine(IsVideosLibraryCapability.ToString());
            output.Append("IsVideosLibraryCapability:\t").AppendLine(IsVideosLibraryCapability.ToString());
            output.Append("IsMusicLibraryCapability:\t").AppendLine(IsMusicLibraryCapability.ToString());

            LogHelper.LogInfo(output.ToString(), typeof(AppxManifestHelper), "OutPutAppCapabilityInfo");
        }
        #endregion  ******************************应用权限信息******************************


        private static void OutputPackageInfo()        
        {            
            Package package = Package.Current;
            PackageId packageId = package.Id;
            PackageVersion version = packageId.Version;

            String output = String.Format(
                               "Name: \"{0}\"\n" +
                               "Version: {1}.{2}.{3}.{4}\n" +
                               "Architecture: {5}\n" +
                               "ResourceId: \"{6}\"\n" +
                               "Publisher: \"{7}\"\n" +
                               "PublisherId: \"{8}\"\n" +
                               "FullName: \"{9}\"\n" +
                               "FamilyName: \"{10}\"\n" +
                               "IsFramework: {11}\n",
                               "Author: \"{12}\"",
                               packageId.Name,
                               version.Major, version.Minor, version.Build, version.Revision,
                               packageId.Architecture,
                               packageId.ResourceId,
                               packageId.Publisher,
                               packageId.PublisherId,
                               packageId.FullName,
                               packageId.FamilyName,
                               package.IsFramework,
                               "packageId.Author"//不能使用这个属性(System.InvalidCastException: Unable to cast object of type 'Windows.ApplicationModel.PackageId' to type 'Windows.Phone.ApplicationModel.IPackageIdWithMetadata'.)
                               );

            LogHelper.LogInfo(output.ToString(), typeof(AppxManifestHelper), "OutputPackageInfo");
        }

    }
}
